﻿using UnityEngine;
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using LuaInterface;
using UnityEngine.UI;
using TMPro;
using Spine.Unity;
using SimpleJSON;
using Spine;
using UnityEngine.EventSystems;
using DG.Tweening;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.HSSF.UserModel;
using System.Linq;
using LitJson;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using ZXing;
using ZXing.QrCode;

#if UNITY_EDITOR
// using System.Diagnostics;
using UnityEditor;
#endif

namespace YanhuaMMO
{
    public class Util
    {
        private static List<string> luaPaths = new List<string>();
        public const double DOUBLE_DELTA = 1E-06;       // 浮点型的误差

        private static RandomFactory randomFac;
        public static int Int(object o)
        {
            return Convert.ToInt32(o);
        }

        public static float Float(object o)
        {
            return (float)Math.Round(Convert.ToSingle(o), 2);
        }

        public static long Long(object o)
        {
            return Convert.ToInt64(o);
        }

        public static int RandomInt(int min, int max)
        {
            return UnityEngine.Random.Range(min, max);
        }

        public static float Random(float min, float max)
        {
            return UnityEngine.Random.Range(min, max);
        }

        public static string Uid(string uid)
        {
            int position = uid.LastIndexOf('_');
            return uid.Remove(0, position + 1);
        }

        public static long GetTime()
        {
            TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0).Ticks);
            return (long)ts.TotalMilliseconds;
        }

        /// <summary>
        /// 搜索子物体组件-GameObject版
        /// </summary>
        public static T Get<T>(GameObject go, string subnode) where T : Component
        {
            if (go != null)
            {
                Transform sub = go.transform.Find(subnode);
                if (sub != null) return sub.GetComponent<T>();
            }
            return null;
        }

        /// <summary>
        /// 搜索子物体组件-Transform版
        /// </summary>
        public static T Get<T>(Transform go, string subnode) where T : Component
        {
            if (go != null)
            {
                Transform sub = go.Find(subnode);
                if (sub != null) return sub.GetComponent<T>();
            }
            return null;
        }

        /// <summary>
        /// 搜索子物体组件-Component版
        /// </summary>
        public static T Get<T>(Component go, string subnode) where T : Component
        {
            return go.transform.Find(subnode).GetComponent<T>();
        }

        /// <summary>
        /// 添加组件
        /// </summary>
        public static T Add<T>(GameObject go) where T : Component
        {
            if (go != null)
            {
                T[] ts = go.GetComponents<T>();
                for (int i = 0; i < ts.Length; i++)
                {
                    if (ts[i] != null) GameObject.Destroy(ts[i]);
                }
                return go.gameObject.AddComponent<T>();
            }
            return null;
        }

        /// <summary>
        /// 添加组件
        /// </summary>
        public static T Add<T>(Transform go) where T : Component
        {
            return Add<T>(go.gameObject);
        }

        /// <summary>
        /// 查找子对象
        /// </summary>
        public static GameObject Child(GameObject go, string subnode)
        {
            return Child(go.transform, subnode);
        }

        /// <summary>
        /// 查找子对象
        /// </summary>
        public static GameObject Child(Transform go, string subnode)
        {
            Transform tran = go.Find(subnode);
            if (tran == null) return null;
            return tran.gameObject;
        }

        /// <summary>
        /// 取平级对象
        /// </summary>
        public static GameObject Peer(GameObject go, string subnode)
        {
            return Peer(go.transform, subnode);
        }

        /// <summary>
        /// 取平级对象
        /// </summary>
        public static GameObject Peer(Transform go, string subnode)
        {
            Transform tran = go.parent.Find(subnode);
            if (tran == null) return null;
            return tran.gameObject;
        }

        /// <summary>
        /// 计算字符串的MD5值
        /// </summary>
        public static string md5(string source)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] data = System.Text.Encoding.UTF8.GetBytes(source);
            byte[] md5Data = md5.ComputeHash(data, 0, data.Length);
            md5.Clear();

            string destString = "";
            for (int i = 0; i < md5Data.Length; i++)
            {
                destString += System.Convert.ToString(md5Data[i], 16).PadLeft(2, '0');
            }
            destString = destString.PadLeft(32, '0');
            return destString;
        }

        /// <summary>
        /// 计算文件的MD5值
        /// </summary>
        public static string md5file(string file)
        {
            try
            {
                FileStream fs = new FileStream(file, FileMode.Open);
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(fs);
                fs.Close();

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("md5file() fail, error:" + ex.Message);
            }
        }

        public static string md5fileAndLength(string file, out long bCount)
        {
            try
            {
                FileStream fs = new FileStream(file, FileMode.Open);
                bCount = fs.Length;
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(fs);
                fs.Close();

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("md5file() fail, error:" + ex.Message);
            }
        }

        /// <summary>
        /// 清除所有子节点
        /// </summary>
        public static void ClearChild(Transform go)
        {
            if (go == null) return;
            for (int i = go.childCount - 1; i >= 0; i--)
            {
                GameObject.Destroy(go.GetChild(i).gameObject);
            }
        }

        /// <summary>
        /// 清理内存
        /// </summary>
        public static void ClearMemory()
        {
            GC.Collect();
            Resources.UnloadUnusedAssets();
            LuaManager mgr = AppFacade.Instance.GetManager<LuaManager>(ManagerName.Lua);
            if (mgr != null) mgr.LuaGC();
        }
        public static string LogPath
        {
            get
            {
                string game = AppConst.AppName.ToLower();
                if (Application.isMobilePlatform)
                {
                    return Application.persistentDataPath + "/" + game + "/";
                }
                if (Application.platform == RuntimePlatform.OSXEditor)
                {
                    int i = Application.dataPath.LastIndexOf('/');
                    return Application.dataPath.Substring(0, i + 1) + game + "/";
                }
                return Application.dataPath.Replace("Assets", "") + "Log/";
            }
        }
        /// <summary>
        /// 取得数据存放目录
        /// </summary>
        public static string DataPath
        {
            get
            {
                string game = AppConst.AppName.ToLower();
                if (Application.isMobilePlatform)
                {
                    return Application.persistentDataPath + "/" + game + "/";
                }
                /*
                if (AppConst.DebugMode)
                {
                    return Application.dataPath + "/" + AppConst.AssetDir + "/";
                }
                */
                if (Application.platform == RuntimePlatform.OSXEditor)
                {
                    int i = Application.dataPath.LastIndexOf('/');
                    return Application.dataPath.Substring(0, i + 1) + game + "/";
                }
                return "D:/" + game + "/";
            }
        }

        /// <summary>
        /// 取得战报目录
        /// </summary>
        public static string FightReportPath
        {
            get
            {
                string game = AppConst.AppName.ToLower();
                if (Application.isMobilePlatform)
                {
                    return Application.streamingAssetsPath + "/MapFile/";
                }
                /*
                if (AppConst.DebugMode)
                {
                    return Application.dataPath + "/" + AppConst.AssetDir + "/";
                }
                */
                if (Application.platform == RuntimePlatform.OSXEditor)
                {
                    return "file://" + Application.streamingAssetsPath + "/MapFile/";
                }
                return Application.streamingAssetsPath + "/MapFile/";
            }
        }

        public static string GetRelativePath()
        {
            if (Application.isEditor)
                // return "file://" + System.Environment.CurrentDirectory.Replace("\\", "/") + "/Assets/" + AppConst.AssetDir + "/";
                return "file:///" + DataPath;
            else if (Application.isMobilePlatform || Application.isConsolePlatform)
                return "file:///" + DataPath;
            else // For standalone player.
                return "file://" + Application.streamingAssetsPath + "/";
        }

        public static string GetDataPath()
        {
            if (Application.isEditor)
                // return "file://" + System.Environment.CurrentDirectory.Replace("\\", "/") + "/Assets/" + AppConst.AssetDir + "/";
                return DataPath;
            else if (Application.isMobilePlatform || Application.isConsolePlatform)
                return DataPath;
            else // For standalone player.
                return Application.streamingAssetsPath + "/";
        }


        /// <summary>
        /// 取得行文本
        /// </summary>
        public static string GetFileText(string path)
        {
            return File.ReadAllText(path);
        }

        /// <summary>
        /// 网络可用
        /// </summary>
        public static bool NetAvailable
        {
            get
            {
                return Application.internetReachability != NetworkReachability.NotReachable;
            }
        }

        /// <summary>
        /// 是否是无线
        /// </summary>
        public static bool IsWifi
        {
            get
            {
                return Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork;
            }
        }

        /// <summary>
        /// 应用程序内容路径
        /// </summary>
        public static string AppContentPath()
        {
            string path = string.Empty;
            switch (Application.platform)
            {
                case RuntimePlatform.Android:
                    path = "jar:file://" + Application.dataPath + "!/assets/";
                    break;
                case RuntimePlatform.IPhonePlayer:
                    path = Application.dataPath + "/Raw/";
                    break;
                default:
                    path = Application.dataPath + "/" + AppConst.AssetDir + "/";
                    break;
            }
            return path;
        }
        public static void DeleteFile(string fileName)
        {
            string dataPath = Util.DataPath + fileName;  //数据目录
            if (File.Exists(dataPath))
            {
                File.Delete(dataPath);
            }
        }
        /// <summary>
        /// 删除热更内容根目录，仅用来修复客户端功能
        /// </summary>
        public static void DeleteYanHuaMmoFile()
        {
            string path = Util.DataPath.Substring(0, Util.DataPath.Length - 1);
            if(Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.OSXEditor)
                path = path.Replace('/', '\\');

            if (Directory.Exists(path))
            {
                Directory.Delete(path, true);
            }
        }
        public static string ReadFightReport(string fileName)
        {
            string dataPath = Util.FightReportPath + fileName;  //数据目录
            StreamReader sw = null;
            try
            {
                if (!File.Exists(dataPath))
                    return "";

                sw = new StreamReader(dataPath);
                string str = sw.ReadToEnd();
                return str;

            }
            catch (Exception e) { }
            finally
            {
                if (sw != null)
                {
                    sw.Close();
                    sw.Dispose();
                }

            }
            return "";
        }

        public static void WriteToFileAsync(string fileName, string str, bool isAppend = true)
        {
            FileWriteAsync.Write(Util.LogPath, fileName, str, isAppend);
        }
        public static void WriteToFile(string fileName, string str, bool isAppend = true)
        {
            string dataPath = Util.DataPath + fileName;  //数据目录
            StreamWriter sw = null;
            try
            {
                if (File.Exists(dataPath) && isAppend)
                {
                    sw = new StreamWriter(dataPath, true);
                }
                else
                {
                    if (!Directory.Exists(Util.DataPath))
                        Directory.CreateDirectory(Util.DataPath);
                    sw = new StreamWriter(dataPath, false);
                }
                sw.WriteLine(str);

            }
            catch (Exception e) { }
            finally
            {
                if (sw != null)
                {
                    sw.Close();
                    sw.Dispose();
                }

            }
        }
        public static void Log(string str)
        {
            Debug.Log(str);
            if (AppConst.DebugMode)
            {
                //Debug.Log(str);
                string dataPath = Util.DataPath + "log.txt";  //数据目录
                WriteToFile("log.txt", str);
            }
        }

        public static void LogWarning(string str)
        {
            Debug.LogWarning(str);
        }


        public static void LogError(string str, bool export = true)
        {
            Debug.LogError(str);
            if (export)
            {
                string dataPath = Util.DataPath + "error.txt";  //数据目录
                StreamWriter sw = null;
                try
                {
                    if (File.Exists(dataPath))
                    {
                        sw = new StreamWriter(dataPath, true);
                    }
                    else
                    {
                        Debug.Log(dataPath);
                        sw = new StreamWriter(dataPath, false);
                    }
                    sw.WriteLine(str);

                }
                catch (Exception e) { }
                finally
                {
                    if (sw != null)
                    {
                        sw.Close();
                        sw.Dispose();
                    }

                }

            }
        }

        //日期格式化
        public static string TimeDateFormat(string Startimestamp)
        {
            long jsTimeStamp = long.Parse(Startimestamp);
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区
            DateTime dt = startTime.AddMilliseconds(jsTimeStamp);
            return dt.ToString("yyyy/MM/dd");
        }

        //剩余时间格式化
        public static string RemainTimeFormat(string Endtimestamp)
        {
            long jsTimeStamp = long.Parse(Endtimestamp);
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区
            long timeStamp = (long)(DateTime.Now - startTime).TotalMilliseconds;

            long remainTime = timeStamp - jsTimeStamp;
            return remainTime.ToString();
        }


        /// <summary>
        /// 防止初学者不按步骤来操作
        /// </summary>
        /// <returns></returns>
        public static int CheckRuntimeFile()
        {
            if (!Application.isEditor) return 0;
            string streamDir = Application.dataPath + "/StreamingAssets/";
            if (!Directory.Exists(streamDir))
            {
#if !UNITY_EDITOR
                return -1;
#else
                return 0;
#endif
            }
            else
            {
                string[] files = Directory.GetFiles(streamDir);
                if (files.Length == 0) return -1;

                if (!File.Exists(streamDir + "files.txt"))
                {
                    return -1;
                }
            }
            string sourceDir = AppConst.FrameworkRoot + "/ToLua/Source/Generate/";
            if (!Directory.Exists(sourceDir))
            {
                return -2;
            }
            else
            {
                string[] files = Directory.GetFiles(sourceDir);
                if (files.Length == 0) return -2;
            }
            return 0;
        }

        /// <summary>
        /// 执行Lua方法
        /// </summary>
        public static object[] CallMethod(string module, string func, params object[] args)
        {
            return CallDisposeMethod(module, func, args);
            LuaManager luaMgr = AppFacade.Instance.GetManager<LuaManager>(ManagerName.Lua);
            if (luaMgr == null)
                return null;
            return luaMgr.CallFunction(module + "." + func, args);
        }

        public static object[] CallDisposeMethod(string module, string func, params object[] args)
        {
            object[] objs = null;

            LuaManager luaMgr = AppFacade.Instance.GetManager<LuaManager>(ManagerName.Lua);
            if (luaMgr != null)
            {
                LuaTable luaTable = luaMgr.GetTable(module);
                if (luaTable != null)
                {
                    var luaFunc = luaTable.GetLuaFunction(func);
                    if (luaFunc != null)
                    {
                        objs = luaFunc.LazyCall(args);
                        luaFunc.Dispose();
                    }
                    luaTable.Dispose();
                }
            }

            return objs;
        }

        public static LuaTable lookTable(string tableName)
        {
            LuaManager luaMgr = AppFacade.Instance.GetManager<LuaManager>(ManagerName.Lua);
            return luaMgr.lookTable(tableName);
        }

        /// <summary>
        /// 检查运行环境
        /// </summary>
        public static bool CheckEnvironment()
        {
#if UNITY_EDITOR
            int resultId = Util.CheckRuntimeFile();
            if (resultId == -1)
            {
                Debug.LogError("没有找到框架所需要的资源，单击Game菜单下Build xxx Resource生成！！");
                EditorApplication.isPlaying = false;
                return false;
            }
            else if (resultId == -2)
            {
                Debug.LogError("没有找到Wrap脚本缓存，单击Lua菜单下Gen Lua Wrap Files生成脚本！！");
                EditorApplication.isPlaying = false;
                return false;
            }
            if (Application.loadedLevelName == "Test" && !AppConst.DebugMode)
            {
                Debug.LogError("测试场景，必须打开调试模式，AppConst.DebugMode = true！！");
                EditorApplication.isPlaying = false;
                return false;
            }
#endif
            return true;
        }

        public static void SetPlayerPrefs(string key, string value)
        {
            PlayerPrefs.SetString(key, value);
        }
        public static string GetPlayerPrefs(string key)
        {
            if (PlayerPrefs.HasKey(key))
            {
                return PlayerPrefs.GetString(key);
            }
            return null;
        }

        public static void SetUserName(string name)
        {
            PlayerPrefs.SetString("accountName", name);
        }
        public static void SetPassword(string pwd)
        {
            PlayerPrefs.SetString("password", pwd);
        }

        public static string GetUserName()
        {
            if (PlayerPrefs.HasKey("accountName"))
            {
                return PlayerPrefs.GetString("accountName");
            }
            return null;
        }
        public static string GetPassword()
        {
            if (PlayerPrefs.HasKey("password"))
            {
                return PlayerPrefs.GetString("password");
            }
            return null;
        }

        public static void SetBtnTransition(GameObject go, Sprite s)
        {
            go.GetComponent<Button>().transition = Selectable.Transition.SpriteSwap;
            SpriteState tmpSpriteState = new SpriteState();
            tmpSpriteState.disabledSprite = s;
            tmpSpriteState.pressedSprite = s;
            go.GetComponent<Button>().spriteState = tmpSpriteState;
        }

        //通用foreach方法
        public static List<object> ForEach(IEnumerable value)
        {
            List<object> list = new List<object>();
            foreach (var item in value)
            {
                list.Add(item);
            }
            return list;
        }
        public static void EndOfFrame(Action action)
        {
            var panelManager = AppFacade.Instance.GetManager<PanelManager>(ManagerName.Panel);
            panelManager.StartCoroutine(EndOfFrame_Wait(action));
        }
        public static void NextFrame(Action action)
        {
            var panelManager = AppFacade.Instance.GetManager<PanelManager>(ManagerName.Panel);
            panelManager.StartCoroutine(NextFrame_Wait(action));
        }
        public static void WaitForSeconds(Action action, float time)
        {
            var panelManager = AppFacade.Instance.GetManager<PanelManager>(ManagerName.Panel);
            panelManager.StartCoroutine(WaitForSeconds_Wait(action, time));
        }
        private static IEnumerator WaitForSeconds_Wait(Action action, float time)
        {
            yield return new WaitForSeconds(time);
            action?.Invoke();
        }
        private static IEnumerator EndOfFrame_Wait(Action action)
        {
            yield return new WaitForEndOfFrame();
            action?.Invoke();
        }
        private static IEnumerator NextFrame_Wait(Action action)
        {
            yield return 0;
            action?.Invoke();
        }

        public static void SetTextMeshProUGUIAlignment(TextMeshProUGUI Text, int type)
        {
            if (Text != null)
            {
                Text.alignment = (TextAlignmentOptions)type;
            }
        }

        public static void SetTextAlignment(Text Text, int type)
        {
            if (Text != null)
            {
                Text.alignment = (TextAnchor)type;
            }
        }
        //0xee01动作返回channel协议解析
        public static bool GetActionVisibleByChannel(int value, int channel)
        {
            int offsetValue = Mathf.Abs(channel - 5);
            int result = (value >> offsetValue) & 1;
            return result == 1;
        }
        //int转16进制
        public static string IntTo16Hex(int value)
        {
            return string.Format("{0:X}", value);
        }
        public static Color ColorHx16toRGB(string strHxColor)
        {
            try
            {
                if (strHxColor.Length == 0)
                {//如果为空
                    return Color.white;//设为白色
                }
                else
                {//转换颜色
                    float r = int.Parse(strHxColor.Substring(0, 2), System.Globalization.NumberStyles.HexNumber) * 1f / 255;
                    float g = int.Parse(strHxColor.Substring(2, 2), System.Globalization.NumberStyles.HexNumber) * 1f / 255;
                    float b = int.Parse(strHxColor.Substring(4, 2), System.Globalization.NumberStyles.HexNumber) * 1f / 255;
                    return new Color(r, g, b);
                }
            }
            catch
            {//设为黑色
                return Color.white;
            }
        }
        /// <summary>
        /// 屏幕已宽度自适应
        /// 主分辨率720*1280
        /// </summary>
        /// <returns></returns>
        public static float GetScreeWidth()
        {
            return 720;
        }
        public static float GetScreeHeight()
        {
            return 1280;
        }

        public static Vector3 WorldToScreenPoint(Vector3 worldPos, bool isRound = false)
        {
            Vector3 pos = Vector3.zero;
            if (!isRound)
            {
                pos = LuaHelper.GetPanelManager().CameraMain.GetComponent<Camera>().WorldToScreenPoint(worldPos);
                return new Vector3(pos.x / Screen.width * GetScreeWidth() - GetScreeWidth() / 2, pos.y / Screen.height * GetScreeHeight() - GetScreeHeight() / 2, 0);
            }
            else
            {
                pos = LuaHelper.GetPanelManager().CameraRound.GetComponentInChildren<Camera>().WorldToViewportPoint(worldPos);
                return new Vector3(pos.x * GetScreeWidth() - GetScreeWidth() / 2, pos.y * GetScreeHeight() - GetScreeHeight() / 2, 0);
            }
        }

        public static Vector3 WorldToScreenPoint(Camera camera, Vector3 worldPos)
        {
            Vector3 pos = Vector3.zero;
            pos = camera.WorldToViewportPoint(worldPos);
            return new Vector3(pos.x * Screen.width - Screen.width / 2, pos.y * Screen.height - Screen.height / 2, 0);
        }

        public static void QuitGame()
        {
#if UNITY_EDITOR
            UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();

#endif
        }
        //给transform.rotation赋值
        public static Quaternion GetQuaternionByEuler(Vector3 vec)
        {
            return Quaternion.Euler(vec);
        }
        //剧情显示专用
        public static void SetRenderMaterial(GameObject obj, bool isDim = false)
        {
            if (obj == null) return;
            var render = obj.GetComponent<MeshRenderer>();
            if (render != null)
            {
                var tex = render.material.mainTexture;
                obj.layer = LayerMask.NameToLayer("UI");
                render.material.shader = Shader.Find("Unlit/ShowRole_Story");
                //置灰
                render.material.SetFloat("_isDim", isDim ? 1 : 0);
                var height = Screen.height;
                //根据剧情UI设置渐隐分界线高度
                render.material.SetFloat("_HideLine", height);
            }
        }
        public static void PlayAnimationByObject(GameObject obj, string animName, bool isDim = false)
        {
            if (obj == null) return;
            SetRenderMaterial(obj, isDim);
            var nameList = animName.Split(';');
            var anim = obj.GetComponent<SkeletonAnimation>();
            if (anim == null) return;
            var stateData = new AnimationStateData(anim.skeleton.Data);
            var panelManager = AppFacade.Instance.GetManager<PanelManager>(ManagerName.Panel);
            panelManager.StartCoroutine(PlayAnimation_Story(nameList, anim, stateData, obj, isDim));

        }
        private static IEnumerator PlayAnimation_Story(string[] nameList, SkeletonAnimation anim, AnimationStateData stateData, GameObject obj, bool isDim)
        {
            for (int i = 1; i < nameList.Length; i++)
            {
                if (obj == null) break;
                var spineAnim = anim.skeleton.Data.FindAnimation(nameList[i]);

                if (spineAnim == null) break;
                var time = spineAnim.Duration;
                anim.state.SetAnimation(0, spineAnim, (i + 1) == nameList.Length);
                yield return new WaitForEndOfFrame();
                SetRenderMaterial(obj, isDim);
                if ((i + 1) < nameList.Length)
                {
                    var spineAnim2 = anim.skeleton.Data.FindAnimation(nameList[i + 1]);
                    if (spineAnim2 != null) stateData.SetMix(spineAnim, spineAnim2, 0.2f);
                    yield return new WaitForSeconds(time);
                }
            }
            yield return 0;
        }

        public static float SetActionTimeScale(SkeletonAnimation anim, string animName, float timeScale = 1)
        {
            if (anim != null && anim.skeleton != null && anim.state != null && animName != null && animName.Length > 0)
            {
                var ani = anim.skeleton.Data.FindAnimation(animName);
                if (ani != null)
                {
                    anim.timeScale = timeScale;
                }
            }

            return 0;

        }

        public static float PlayAction(SkeletonAnimation anim, string animName, bool loop = true, float time = -1, bool isEffect = false, float timeScale = 1)
        {
            if (anim != null && anim.skeleton != null && anim.state != null && animName != null && animName.Length > 0)
            {
                var ani = anim.skeleton.Data.FindAnimation(animName);
                if (ani != null)
                {
                    if (isEffect)
                    {
                        anim.timeScale = 1;
                        anim.skeleton.SetToSetupPose();
                        anim.state.ClearTracks();
                    }

                    anim.timeScale = timeScale;
                    TrackEntry entry = anim.state.SetAnimation(0, ani, loop);

                    float duration = anim.skeleton.Data.FindAnimation(animName).Duration;
                    if (time > 0)
                    {
                        //entry.TimeScale = duration / time;
                        duration = time;
                    }
                    else
                    {
                        //entry.TimeScale = timeScale;
                        duration = duration / timeScale;
                    }

                    return duration;
                }
                else
                {
                    LogError("Spine Animation not find: animName = " + animName + ", go.name = " + anim.transform.parent.name);
                }

            }

            return 0;
        }

        public static float PlayAction(GameObject obj, string animName, bool loop = true, float time = -1, bool isEffect = false, float timeScale = 1)
        {
            if (obj != null && animName.Length > 0)
            {
                var anim = obj.GetComponent<SkeletonAnimation>();
                return PlayAction(anim, animName, loop, time, isEffect, timeScale);
            }

            return 0;
        }

        //这个time的使用意思不明，现在只有UI在用，不修改了（timeScale等）
        public static float AddAction(GameObject obj, string animName, bool loop = true, float time = -1, bool isEffect = false)//, float timeScale = 1
        {
            if (obj != null && animName.Length > 0)
            {
                var anim = obj.GetComponent<SkeletonGraphic>();

                var name = anim.Skeleton.Data.FindAnimation(animName);
                if (anim != null && name != null)
                {
                    if (isEffect)
                    {
                        anim.Skeleton.SetToSetupPose();
                        anim.AnimationState.ClearTracks();
                    }
                    TrackEntry entry = anim.AnimationState.AddAnimation(0, name, loop, 0);

                    float duration = anim.Skeleton.Data.FindAnimation(animName).Duration;
                    if (time > 0)
                    {
                        entry.TimeScale = time;// duration / time
                        // entry.TimeScale = duration / time;
                        // duration = time;
                    }
                    else
                    {
                        entry.TimeScale = 1;
                        // entry.TimeScale = timeScale;
                        // duration = duration / timeScale;
                    }


                    return duration;
                }
                else
                {
                    Util.LogError("cannot find:" + animName);
                }

            }

            return 0;
        }

        public static void PauseCurrentAction(GameObject obj)
        {
            if (obj != null)
            {
                var anim = obj.GetComponent<SkeletonAnimation>();
                if (anim && anim.state != null)
                {
                    var trackEntry = anim.state.GetCurrent(0);
                    if (trackEntry != null)
                    {
                        trackEntry.TimeScale = 0;
                    }
                }
            }
        }
        /// <summary>
        /// 继续当前动作
        /// </summary>
        public static void ResumeCurrentAction(GameObject obj, float timeScale = 1)
        {
            if (obj != null)
            {
                var anim = obj.GetComponent<SkeletonAnimation>();
                if (anim && anim.state != null)
                {
                    var trackEntry = anim.state.GetCurrent(0);
                    if (trackEntry != null)
                    {
                        trackEntry.TimeScale = timeScale;
                    }
                }
            }
        }


        public static void SetFlipX(SkeletonAnimation anim, bool b)
        {
            if (anim && anim.Skeleton != null)
            {
                anim.Skeleton.FlipX = b;
            }
        }

        public static void SetFlipX(GameObject obj, bool b)
        {
            if (obj != null)
            {
                var anim = obj.GetComponent<SkeletonAnimation>();
                SetFlipX(anim, b);

                // if (anim && anim.Skeleton != null)
                // {
                //     anim.Skeleton.FlipX = b;
                // }
            }
        }

        public static void SetOrder(GameObject obj, int d)
        {
            if (obj != null)
            {
                // var anim = obj.GetComponent<SkeletonAnimation>();
                var mesh = obj.GetComponent<MeshRenderer>();
                if (mesh)
                {
                    mesh.sortingOrder = d;
                }
            }
        }
        public static void SetLayerMask(GameObject obj, string layerMask, bool includeChild)
        {
            SetLayerMask(obj, LayerMask.NameToLayer(layerMask), includeChild);
        }
        public static void SetLayerMask(GameObject obj, int layer, bool includeChild)
        {
            if (obj != null)
            {
                obj.layer = layer;
                if (includeChild)
                {
                    var t = obj.transform;
                    int count = t.childCount;
                    for (int i = 0; i < count; i++)
                    {
                        SetLayerMask(t.GetChild(i).gameObject, layer, includeChild);
                    }
                }
            }
        }
        public static bool SetSkin(GameObject obj, string skinName)
        {
            if (obj != null && !string.IsNullOrEmpty(skinName))
            {
                var anim = obj.GetComponent<SkeletonAnimation>();
                if (!anim || anim.Skeleton == null || anim.Skeleton.Data == null)
                    return false;

                var data = anim.Skeleton.Data;
                if (data == null)
                    return false;

                Skin foundSkin = data.FindSkin(skinName);
                if (foundSkin == null)
                    return false;

                anim.Skeleton.SetSkin(foundSkin);
                // data.DefaultSkin = foundSkin;
                return true;
            }

            return false;
        }

        public static void TintObj(GameObject obj, Color color)
        {
            MaterialPropertyBlock mpb = new MaterialPropertyBlock();
            mpb.SetColor("_Color", color);
            MeshRenderer mr = obj.transform.Find("Animation").GetComponent<MeshRenderer>();
            mr.SetPropertyBlock(mpb);
        }
        //逐帧测试用
        public static void GamePause()
        {
            // EditorApplication.isPaused = true;
        }
        public static void SetRenderTexture(GameObject image)
        {
            //image.GetComponent<RawImage>().texture = LuaHelper.GetPanelManager().ModelCamera.targetTexture;
            // LuaHelper.GetPanelManager().ModelCamera.fieldOfView
        }

        public static bool IsTouchedUI()
        {
            if (Input.GetMouseButtonDown(0) || (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began))
            {
#if (UNITY_ANDROID || UNITY_IPHONE) && !UNITY_EDITOR
                if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
#else
                if (EventSystem.current.IsPointerOverGameObject())
#endif
                    return true;
                else
                    return false;
            }

            return false;
        }

        public static bool TouchSomething()
        {
            Camera camera = ToolsCommons.GetInstance().GetMainCamera();
            if (camera == null)
                return false;

            Ray ray = camera.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            string[] layers = { "monster", "DROP", "Arrow" };

            if (Physics.Raycast(ray, out hit, 1000, LayerMask.GetMask(layers)))
            {
                return true;
            }
            return false;
        }

        public static void DelCanvas(GameObject obj)
        {
            GraphicRaycaster gr = obj.GetComponent<GraphicRaycaster>();
            if (gr)
                GameObject.Destroy(gr);
            Canvas c = obj.GetComponent<Canvas>();
            if (c)
                GameObject.Destroy(c);

            obj.SetActive(false);
        }

        public static void ShowWords(string str, TextMeshProUGUI text)
        {
            var panelManager = AppFacade.Instance.GetManager<PanelManager>(ManagerName.Panel);
            panelManager.StopCoroutine(ShowWord(str, text));
            panelManager.StartCoroutine(ShowWord(str, text));
        }

        private static IEnumerator ShowWord(string str, TextMeshProUGUI text)
        {
            int len = 1;
            while (len <= str.Length)
            {
                text.text = str.Substring(0, len);
                len++;
                yield return new WaitForSeconds(0.05f);
            }
            yield break;
        }

        public static void SetGameObjectPos(GameObject go, Vector3 pos)
        {
            go.transform.localPosition = pos;
        }

        public static void SetGameObjectScale(GameObject go, Vector3 scales)
        {
            go.transform.localScale = scales;
        }

        public static void SetGameObjectParent(GameObject go, Transform tparent)
        {
            go.transform.SetParent(tparent);
        }

        public static void SetGameObjectParent(GameObject go, GameObject go_parent)
        {
            go.transform.SetParent(go_parent.transform);
        }


        public static void SetGameObjectParent(Transform child_transform, Transform tparent)
        {
            child_transform.SetParent(tparent);
        }

        public static void SetGameObjectParent(Transform child_transform, GameObject go_parent)
        {
            child_transform.SetParent(go_parent.transform);
        }

        public static void SetGameObjectRotate(GameObject go, Vector3 rot)
        {
            go.transform.localRotation = Quaternion.Euler(rot.x, rot.y, rot.z);
        }
        public static void resetRandomFac(string seed)
        {
            long seedd = long.Parse(seed);
            randomFac = new RandomFactory(seedd);
        }
        public static int getRandomInt(int range)
        {
            return randomFac.NextInt(range);
        }

        public static double Rand(double u, double d)
        {
            double u1, u2, z, x;
            //Random ram = new Random();
            if (d <= 0)
            {
                return u;
            }
            u1 = UnityEngine.Random.Range(0f, 1f);
            u2 = UnityEngine.Random.Range(0f, 1f);

            z = Math.Sqrt(-2 * Math.Log(u1)) * Math.Sin(2 * Math.PI * u2);

            x = u + d * z;
            return x;

        }

        public static void doSizeDeltaAnim(RectTransform rect, Vector2 endValue, float duaration, LuaFunction callback = null)
        {
            Tween tt = rect.DOSizeDelta(endValue, duaration).SetEase(Ease.InExpo);
            tt.onComplete = () =>
            {
                if (callback != null)
                    callback.Call();
            };

        }
        public static void SetVideoPlayer(GameObject videoObj, UnityEngine.Video.VideoClip mov)
        {
            if (videoObj != null)
            {

                var videoCom = videoObj.GetComponent<UnityEngine.Video.VideoPlayer>();
                videoCom.clip = mov;
                videoCom.audioOutputMode = UnityEngine.Video.VideoAudioOutputMode.AudioSource;
                videoCom.SetTargetAudioSource(0, videoObj.GetComponent<AudioSource>());
                videoCom.IsAudioTrackEnabled(0);
                videoCom.loopPointReached += finishVideo;
                SoundManager.Instance.EnabledBg(false);
                videoObj.SetActive(false);
                videoObj.SetActive(true);
                videoCom.Play();
            }
        }

        public static void DoColor(Image Img, Color endValue, float duaration, LuaFunction callback = null)
        {
            Tween tt = Img.DOColor(endValue, duaration);
            tt.onComplete = () =>
            {
                if (callback != null)
                    callback.Call();
            };
        }

        public static void finishVideo(UnityEngine.Video.VideoPlayer vPlayer)
        {
            CallMethod("UIStory", "finishVideo", new object[] { vPlayer.gameObject });
            SoundManager.Instance.EnabledBg(true);
            vPlayer.loopPointReached -= finishVideo;
        }

        public static void SetSkelSkin(GameObject skeobj, string SkinName)
        {
            if (skeobj != null)
            {
                var SkeCom = skeobj.GetComponent<SkeletonGraphic>().Skeleton;
                SkeCom.SetSkin(SkinName);
            }
        }

        public static void showDigitalJump(TextMeshProUGUI txt, int startnum, int endnum, float deltatime, string endstr = "")
        {
            Sequence mScoreSequence;
            //函数内初始化
            mScoreSequence = DOTween.Sequence();
            //函数内设置属性
            mScoreSequence.SetAutoKill(false);

            mScoreSequence.Append(DOTween.To(delegate (float value)
            {
                //向下取整
                var temp = Math.Floor(value);
                //向Text组件赋值
                txt.text = temp + endstr;
            }, startnum, endnum, deltatime));
        }

        public static void showHitWhiteEff(GameObject ani, float phase)
        {
            // Renderer red = ani.GetComponent<MeshRenderer>();

            // red.material.SetFloat("_FillPhase", phase);
            MaterialPropertyBlock mpb = new MaterialPropertyBlock();
            mpb.SetFloat("_FillPhase", phase);
            MeshRenderer mr = ani.GetComponent<MeshRenderer>();
            mr.SetPropertyBlock(mpb);


        }
        private static StringBuilder stringBuilder = new StringBuilder();
        public static string StringBuilderContent(params object[] str)
        {
            stringBuilder.Clear();
            for (int i = 0; i < str.Length; ++i)
            {
                stringBuilder.Append(str[i]);
            }
            return stringBuilder.ToString();
        }

        public static void addPerspective(GameObject obj)
        {
            obj.AddComponent<PerspectiveScale>();
        }

        public static Dictionary<string, JSONObject> ExcelDataToJson(string filePathName)
        {
            Dictionary<string, JSONObject> listSheet = new Dictionary<string, JSONObject>();
            FileStream fs = new FileStream(filePathName, FileMode.Open, FileAccess.Read);
            if (fs != null)
            {
                ISheet st;
                IWorkbook wk = null;

                if (filePathName.IndexOf(".xlsx") > 0) // 2007版本
                    wk = new XSSFWorkbook(fs);
                else if (filePathName.IndexOf(".xls") > 0) // 2003版本
                    wk = new HSSFWorkbook(fs);
                fs.Close();

                if (wk != null)
                {
                    bool isChinese = false;

                    for (int i = 0; i < wk.NumberOfSheets; i++)
                    {
                        st = wk.GetSheetAt(i);

                        //判断sheet名字是否有汉字，有，则该表不进行加载写入
                        for (int j = 0; j < st.SheetName.Length; j++)
                        {
                            if ((int)st.SheetName[j] > 0x4E00 && (int)st.SheetName[j] < 0x9FA5)
                            {
                                isChinese = true;
                            }
                        }

                        if (!isChinese)
                        {
                            ISheet sheet = st;

                            string cell = null;

                            if (sheet != null)
                            {
                                JSONObject dataTotal = new JSONObject();

                                IRow row = sheet.GetRow(1);                                         //属性行

                                int rowCount = 0;
                                int cellCount = 0;

                                //row.lastCellNum和row.Cells.Count计算列数 大坑 不精确
                                if (row != null)
                                {
                                    for (int m = 0; m < row.LastCellNum + 3; m++)
                                    {
                                        if (row.GetCell(m) != null && row.GetCell(m).ToString() != "")
                                        {
                                            cellCount = m;                                               //精确列数,有效总列数为cellCount + 1;
                                        }
                                    }
                                }

                                for (int n = 0; n < sheet.LastRowNum + 3; n++)
                                {
                                    if (sheet.GetRow(n) != null && sheet.GetRow(n).GetCell(0) != null && sheet.GetRow(n).GetCell(0).ToString() != "")
                                    {
                                        rowCount = n;                                                //精确行数,有效总行数为rowCount + 1;
                                    }
                                }

                                //存属性用于写入
                                for (int j = 0; j < cellCount + 1; ++j)
                                {
                                    if (row != null && row.GetCell(j) != null && row.GetCell(j).ToString() != "")
                                    {
                                        dataTotal["attributeName"][j] = row.GetCell(j).ToString();
                                    }
                                    else
                                    {
                                        continue;
                                    }
                                }

                                //存数据用于写入
                                IRow dataRow = sheet.GetRow(0);                                              //初始值
                                for (int x = 0; x < rowCount + 1; ++x)                                       //遍历整张sheet表数据
                                {
                                    dataRow = sheet.GetRow(x);
                                    if (dataRow == null)
                                    {
                                        LogError("[excel]" + filePathName + " 已忽视无效的行:" + sheet.SheetName + ",row:" + x);
                                        continue;
                                    }
                                    for (int j = 0; j < cellCount + 1; ++j)
                                    {
                                        if (row != null && row.GetCell(j) != null && row.GetCell(j).ToString() != "")
                                        {
                                            if (dataRow != null)
                                            {
                                                if (dataRow.GetCell(j) != null && dataRow.GetCell(j).ToString() != "")
                                                {
                                                    cell = dataRow.GetCell(j).ToString();
                                                }
                                                else
                                                {
                                                    cell = "";
                                                }
                                            }
                                        }
                                        else
                                        {
                                            continue;
                                        }

                                        dataTotal["data"][x][j] = cell;

                                        if (dataRow.GetCell(0) != null)
                                        {
                                            //存id用于写入
                                            dataTotal["id"][x] = dataRow.GetCell(0).ToString();
                                        }
                                        else
                                        {
                                            dataTotal["id"][x] = "";
                                        }
                                    }
                                }
                                listSheet.Add(st.SheetName, dataTotal);
                            }
                        }
                    }
                    wk.Close();
                }
            }
            return listSheet;        //返回Excel所有sheet表数据
        }

        //创建lua文件并写入数据
        public static void SheetDataToLua(string folderPath, string sheetName, JSONObject sheetData)
        {
            if (sheetData != null && sheetName != null)
            {
                JSONNode data = sheetData["data"];
                JSONNode ids = sheetData["id"];
                JSONNode attributes = sheetData["attributeName"];

                if (data != null && attributes != null && ids != null)
                {
                    //创建lua文件
                    //sheetName = sheetName.Replace("t_", "T_");

                    string path = folderPath + "/" + sheetName + ".lua";

                    FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);

                    fs.Close();

                    //开始写入数据
                    ///StreamWriter第二个参数为false覆盖现有文件，为true则把文本追加到文件末尾
                    StreamWriter st = new StreamWriter(path, false);

                    st.Write("return {[" + "\"_key_\"" + "] = {");

                    for (int i = 0; i < attributes.Count; i++)
                    {
                        if (attributes[i] != null)
                        {
                            st.Write(attributes[i].ToString());
                            if (i != attributes.Count - 1)
                            {
                                st.Write(",");
                            }
                        }
                    }
                    st.WriteLine("},");


                    for (int i = 0; i < data.Count; i++)                //data从第五行开始存储
                    {
                        if (i >= 5 && data[i] != null && ids[i] != null)
                        {
                            if (ids[i] == "$")
                            {
                                continue;
                            }
                            if (ids[i] == "#")
                            {
                                break;
                            }
                            if (data[2][0] != null && (data[2][0] == ("int").ToString() || data[2][0] == ""))
                            {
                                st.Write("[" + ids[i] + "] = {");
                            }
                            else
                            {
                                st.Write("[\"" + ids[i] + "\"] = {");
                            }

                            for (int j = 0; j < attributes.Count; j++)
                            {
                                if (attributes[j] != null && data[i][j] != null)
                                {
                                    if (data[2] != null && (data[2][j] == ("int").ToString() || data[2][j] == ""))
                                    {
                                        st.Write(data[i][j].AsInt);
                                    }
                                    else
                                    {
                                        st.Write(data[i][j].ToString().Replace("\\\\n", "\\n"));
                                    }

                                    if (j != attributes.Count - 1)
                                    {
                                        st.Write(",");
                                    }
                                }
                                else
                                {
                                    continue;
                                }

                            }
                            if (i != data.Count - 1)
                            {
                                st.WriteLine("},");
                            }
                            else
                            {
                                st.Write("}");
                            }
                        }
                    }
                    st.Write("}");


                    st.Close();
                }

            }

        }
        public static JSONObject ExcelToDataTable(string filePathName, string sheetName)
        {
            JSONObject dataTotal = new JSONObject();
            FileStream fs = new FileStream(filePathName, FileMode.Open, FileAccess.Read);
            if (fs != null)
            {
                ISheet st;
                IWorkbook wk = null;

                if (filePathName.IndexOf(".xlsx") > 0) // 2007版本
                    wk = new XSSFWorkbook(fs);
                else if (filePathName.IndexOf(".xls") > 0) // 2003版本
                    wk = new HSSFWorkbook(fs);
                fs.Close();                 //fs给Workbook之后就可以关闭了

                if (wk != null)
                {
                    bool isChinese = false;

                    for (int i = 0; i < wk.NumberOfSheets; i++)
                    {
                        st = wk.GetSheetAt(i);
                        //MessageBox.Show(st.SheetName);                //显示工作表名字

                        //判断sheet名字是否有汉字，有，则该表不进行加载写入
                        for (int j = 0; j < st.SheetName.Length; j++)
                        {
                            if ((int)st.SheetName[j] > 0x4E00 && (int)st.SheetName[j] < 0x9FA5)
                            {
                                isChinese = true;
                            }
                        }

                        if (!isChinese && st.SheetName == sheetName)
                        {
                            ISheet sheet = st;

                            string cell = null;

                            if (sheet != null)
                            {
                                IRow Column = sheet.GetRow(4);                                         //判断列数的行
                                IRow row = sheet.GetRow(1);                                         //属性行

                                int rowCount = 0;
                                int cellCount = 0;

                                //row.lastCellNum和row.Cells.Count计算列数 大坑 不精确
                                if (Column != null)
                                {
                                    for (int m = 0; m < Column.LastCellNum; m++)
                                    {
                                        if (Column.GetCell(m) != null && Column.GetCell(m).ToString() != "")
                                        {
                                            cellCount = m;                                               //精确列数，从0开始,有效总列数为cellCount + 1;
                                        }
                                    }
                                }

                                for (int n = 0; n < sheet.LastRowNum + 1; n++)
                                {
                                    if (sheet.GetRow(n) != null && sheet.GetRow(n).GetCell(0) != null && sheet.GetRow(n).GetCell(0).ToString() != "")
                                    {
                                        rowCount = n;                                                //精确行数，从0开始,有效总行数为rowCount + 1;
                                    }
                                }

                                //存属性用于写入
                                for (int j = 0; j < cellCount + 1; ++j)
                                {
                                    if (row != null && row.GetCell(j) != null && row.GetCell(j).ToString() != "")
                                    {
                                        dataTotal["attributeName"][j] = row.GetCell(j).ToString();
                                    }
                                    else
                                    {
                                        dataTotal["attributeName"][j] = "";
                                    }
                                }

                                //存数据用于写入
                                IRow dataRow = sheet.GetRow(0);                                              //初始值

                                for (int x = 4; x < rowCount + 1; ++x)                                       //遍历整张sheet表数据
                                {
                                    dataRow = sheet.GetRow(x);
                                    for (int j = 0; j < cellCount + 1; ++j)
                                    {
                                        string name = dataTotal["attributeName"][j];
                                        if (name == null || name == "")
                                            continue;

                                        if (row != null && row.GetCell(j) != null && row.GetCell(j).ToString() != "")
                                        {
                                            if (dataRow != null)
                                            {
                                                if (dataRow.GetCell(j) != null && dataRow.GetCell(j).ToString() != "")
                                                {
                                                    cell = dataRow.GetCell(j).ToString();
                                                }
                                                else
                                                {
                                                    cell = "";
                                                }
                                            }
                                        }
                                        else
                                        {
                                            continue;
                                        }
                                        if (dataRow.GetCell(0) != null)
                                        {
                                            string attriName = dataTotal["attributeName"][j];
                                            string id = dataRow.GetCell(0).ToString();
                                            dataTotal[id][attriName] = cell;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                wk.Close();
            }
            return dataTotal;
        }

        public static string StringToArr(string Str)
        {
            string dataTotal = "";
            var arr = Str.ToCharArray();
            for (int i = 0; i < arr.Length; i++)
            {
                if (i == 0)
                {
                    dataTotal = arr[i].ToString();
                }
                else
                {
                    dataTotal = dataTotal + "&" + arr[i];
                }

            }
            return dataTotal;
        }

        public static bool ShakeObj(Transform shakeObj, float time, float Strengh, int vebrite, float delayTime = 0)
        {
            var tween = shakeObj.DOShakePosition(time, Strengh, vebrite);
            if (delayTime != 0)
            {
                tween.SetDelay(delayTime);
            }
            return true;
        }


        public static bool setExcelCellValue(string filePathName, String sheetname, JSONNode values, JSONObject configs)
        {
            FileStream fs = new FileStream(filePathName, FileMode.Open, FileAccess.Read);
            if (fs != null)
            {
                ISheet st;
                IWorkbook wk = null;

                if (filePathName.IndexOf(".xlsx") > 0) // 2007版本
                    wk = new XSSFWorkbook(fs);
                else if (filePathName.IndexOf(".xls") > 0) // 2003版本
                    wk = new HSSFWorkbook(fs);
                fs.Close();                 //fs给Workbook之后就可以关闭了

                if (wk != null)
                {
                    ISheet sheet = wk.GetSheet(sheetname);
                    if (sheet != null)
                    {
                        IRow head = sheet.GetRow(1);                                         //属性行
                        Debug.Log(head.LastCellNum);
                        for (int i = 0; i < sheet.LastRowNum + 1; i++)
                        {
                            IRow row = sheet.GetRow(i);                                         //属性行
                            if (row != null && row.GetCell(0) != null && row.GetCell(0).ToString() != "" && row.GetCell(0).ToString() == values[0])
                            {
                                for (int j = 0; j < head.LastCellNum; j++)
                                {
                                    ICell cell = row.GetCell(j, MissingCellPolicy.CREATE_NULL_AS_BLANK);

                                    string name = configs["attributeName"][j];
                                    Debug.Log(name);
                                    Debug.Log(row.GetCell(j).ToString());
                                    Debug.Log(values[name].Value);
                                    if (values[name] != null)
                                    {
                                        if (values[name] != row.GetCell(j).ToString())
                                        {
                                            if (values[name].IsString)
                                            {
                                                cell.SetCellValue(values[name].Value);
                                            }
                                            else
                                            {
                                                cell.SetCellValue(double.Parse(values[name]));
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        FileStream sw = File.Create(filePathName);
                        wk.Write(sw);
                        sw.Close();

                        return true;
                    }
                }
            }
            return false;
        }

        public static bool IsNull(object o)
        {
            if (o is UnityEngine.Object)
            {
                return (o as UnityEngine.Object) == null;
            }
            else if (o is FairyGUI.GObject)
            {
                var obj = o as FairyGUI.GObject;
                return obj == null || obj.displayObject == null || obj.displayObject.gameObject == null;
            }

            return o == null;
        }
        public static bool IsGList(object o)
        {
            return o is FairyGUI.GList;
        }
        public static bool IsGButton(object o)
        {
            return o is FairyGUI.GButton;
        }
        /// <summary>
        /// local x,y,z = Util.Lua_GetPositionXYZ()
        /// 因为原来的return position 会有LuaGC
        /// </summary>
        /// <param name="trans"></param>
        public static void Lua_GetPositionXYZ(Transform obj, out float x, out float y, out float z)
        {
            x = obj.position.x;
            y = obj.position.y;
            z = obj.position.z;
        }
        public static void Lua_SetPositionXYZ(Transform obj, float x, float y, float z)
        {
            obj.position = new Vector3(x, y, z);
        }

        public static void Lua_SetGameObjectPositionXYZ(GameObject obj, float x, float y, float z)
        {
            if (obj == null)
            {
                return;
            }
            var trans = obj.transform;
            var temp = trans.position;
            temp.x = x;
            temp.y = y;
            temp.z = z;
            trans.position = temp;
        }

        public static void Lua_GetLocalPositionXYZ(Transform obj, out float x, out float y, out float z)
        {
            x = obj.localPosition.x;
            y = obj.localPosition.y;
            z = obj.localPosition.z;
        }
        public static void Lua_GetLocalPositionXYZ(GameObject obj, out float x, out float y, out float z)
        {
            Lua_GetLocalPositionXYZ(obj.transform, out x, out y, out z);
        }
        public static void Lua_SetLocalPositionXYZ(Transform obj, float x, float y, float z)
        {
            obj.localPosition = new Vector3(x, y, z);
        }
        public static void Lua_SetLocalPositionXYZ(GameObject obj, float x, float y, float z)
        {
            Lua_SetLocalPositionXYZ(obj.transform, x, y, z);
        }
        public static void Lua_SetLocalScaleXYZ(Transform obj, float x, float y, float z)
        {
            obj.localScale = new Vector3(x, y, z);
        }
        public static void Lua_SetLocalScaleXYZ(GameObject obj, float x, float y, float z)
        {
            Lua_SetLocalScaleXYZ(obj.transform, x, y, z);
        }

        public static void Lua_GetLocalScaleXYZ(Transform obj, out float x, out float y, out float z)
        {
            Vector3 o = obj.localScale;
            x = o.x;
            y = o.y;
            z = o.z;
        }
        public static void Lua_GetLocalScaleXYZ(GameObject obj, out float x, out float y, out float z)
        {
            Lua_GetLocalScaleXYZ(obj.transform, out x, out y, out z);
        }
        public static void Lua_SetLocalRotationXYZ(Transform obj, float x, float y, float z)
        {
            obj.localRotation = Quaternion.Euler(new Vector3(x, y, z));
        }
        public static void Lua_SetLocalRotationXYZ(GameObject obj, float x, float y, float z)
        {
            Lua_SetLocalRotationXYZ(obj.transform, x, y, z);
        }

        public static void Lua_GetLocalRotationXYZ(Transform obj, out float x, out float y, out float z)
        {
            Vector3 o = obj.localEulerAngles;
            x = o.x;
            y = o.y;
            z = o.z;
        }

        public static void Lua_GetLocalRotationXYZ(GameObject obj, out float x, out float y, out float z)
        {
            Lua_GetLocalRotationXYZ(obj.transform, out x, out y, out z);
        }

        public static void Lua_SetGameObjectRotationXYZ(GameObject obj, float rx, float ry, float rz)
        {
            if (obj == null)
            {
                return;
            }
            var trans = obj.transform;
            var temp = trans.eulerAngles;
            temp.x = rx;
            temp.y = ry;
            temp.z = rz;
            trans.eulerAngles = temp;
        }


        public static void Lua_GetWorldToViewportPointXYZ(Camera camera, float inx, float iny, float inz, out float x, out float y, out float z)
        {
            Vector3 o = camera.WorldToViewportPoint(new Vector3(inx, iny, inz));
            x = o.x;
            y = o.y;
            z = o.z;
        }

        public static void Lua_GetBoneWorldXYZ(Bone bone, Transform trans, out float x, out float y, out float z)
        {
            Vector3 o = bone.GetWorldPosition(trans);
            x = o.x;
            y = o.y;
            z = o.z;
        }

        public static void Lua_SetParticleMainStartColor(ParticleSystem sys, float r, float g, float b, float a)
        {
            var main = sys.main;
            main.startColor = new UnityEngine.ParticleSystem.MinMaxGradient(new Color(r, g, b, a));
        }

        public static Transform Lua_SetGameObjectChildLocalEularXYZ(GameObject obj, string childName, float x, float y, float z)
        {
            if (obj == null)
            {
                return null;
            }
            var child = obj.transform.Find(childName);
            if (child)
            {
                child.localEulerAngles = new Vector3(x, y, z);
            }
            return child;
        }

        public static Transform Lua_GameObjectFindTransform(GameObject obj, string childName)
        {
            if (obj == null)
            {
                return null;
            }
            return obj.transform.Find(childName);
        }

        public static Transform Lua_FindTransform(Transform trans, string childName)
        {
            if (trans == null)
            {
                return null;
            }

            return trans.Find(childName);
        }

        public static Transform Lua_FindTransform(GameObject obj, string childName)
        {
            if (obj == null)
            {
                return null;
            }

            return obj.transform.Find(childName);
        }

        public static GameObject Lua_FindGameObject(GameObject obj, string childName)
        {
            if (obj == null)
            {
                return null;
            }
            Transform ret = obj.transform.Find(childName);
            if (ret != null)
            {
                return ret.gameObject;
            }
            return null;
        }

        public static GameObject Lua_FindGameObject(Transform trans, string childName)
        {
            if (trans == null)
            {
                return null;
            }
            Transform ret = trans.Find(childName);
            if (ret != null)
            {
                return ret.gameObject;
            }
            return null;
        }

        public static Component Lua_GameObjectFindComponent(GameObject obj, string childName, string compName)
        {
            if (obj == null)
            {
                return null;
            }
            var child = obj.transform.Find(childName);
            if (child)
            {
                return child.GetComponent(compName);
            }
            return null;
        }

        public static void Lua_TransformAddPosition(Transform obj, float x, float y, float z)
        {
            if (obj == null)
            {
                return;
            }
            var temp = obj.position;
            temp.x += x;
            temp.y += y;
            temp.z += z;
            obj.position = temp;
        }

        // TODO: 确认下是luatable快，还是传 x,y,z 三个参数快
        public static void Lua_GameObjectAddPosAndSetRot(GameObject obj, float x, float y, float z, float rx, float ry, float rz)
        {
            if (obj == null)
            {
                return;
            }
            var trans = obj.transform;

            var temp = trans.position;
            temp.x += x;
            temp.y += y;
            temp.z += z;
            trans.position = temp;

            var tempEuler = trans.eulerAngles;
            tempEuler.x = rx;
            tempEuler.y = ry;
            tempEuler.z = rz;
            trans.eulerAngles = tempEuler;
        }

        public static void Lua_CalcFollowPosition(Spine.Bone followBone, Transform followBoneSpineTrans, Transform followTrans, LuaTable posTable, float x, float y, float z)
        {
            if (posTable == null)
            {
                return;
            }
            if (followBone != null && followBoneSpineTrans != null)
            {
                var newPos = followBone.GetWorldPosition(followBoneSpineTrans);
                posTable["x"] = newPos.x + x;
                posTable["y"] = newPos.y + y;
                posTable["z"] = newPos.z + z;
            }
            else if (followTrans != null)
            {
                var newPos = followTrans.position;
                posTable["x"] = newPos.x + x;
                posTable["y"] = newPos.y + y;
                posTable["z"] = newPos.z + z;
            }
        }

        public static Vector3 Lua_CalcFollowTargetPosition(Spine.Bone followBone, Transform followBoneSpineTrans, Transform followTrans)
        {
            if (followBone != null && followBoneSpineTrans != null)
            {
                return followBone.GetWorldPosition(followBoneSpineTrans);

            }
            else if (followTrans != null)
            {
                return followTrans.position;
            }

            return Vector3.zero;
        }

        public static void Lua_CalcFollowPositionV2(Spine.Bone followBone, Transform followBoneSpineTrans, Transform followTrans, LuaTable posTable, float x, float y, float z)
        {
            if (posTable == null)
            {
                return;
            }
            if (followBone != null && followBoneSpineTrans != null)
            {
                var newPos = followBone.GetWorldPosition(followBoneSpineTrans);
                posTable["x"] = newPos.x + x;
                posTable["y"] = newPos.y + y;
                posTable["z"] = newPos.z + z;
            }
            else if (followTrans != null)
            {
                var newPos = followTrans.position;
                posTable["x"] = newPos.x + x;
                posTable["y"] = newPos.y + y;
                posTable["z"] = newPos.z + z;
            }
        }

        //role 骨骼锚点
        public static Transform GetSpineBoneAsTransform(SkeletonAnimation anim, string boneName, int mode = 0)
        {
            //mode 第一次生成是有效, 0 Follow, 1 Override

            if (!anim || !anim.skeletonDataAsset || string.IsNullOrEmpty(boneName))
            {
                return null;
            }

            SkeletonUtility skeletonUtility = anim.gameObject.GetComponent<SkeletonUtility>();
            if (!skeletonUtility)
            {
                skeletonUtility = anim.gameObject.AddComponent<SkeletonUtility>();
                // skeletonUtility.SpawnHierarchy((SkeletonUtilityBone.Mode)mode, true, true, true);
                skeletonUtility.SpawnHierarchy((SkeletonUtilityBone.Mode)mode, true, true, true);
            }

            Transform boneTrans = FindInChildren(anim.transform, boneName);//anim.transform.Find(boneName);
            return boneTrans;
        }

        public static Transform FindInChildren(Transform trans, string name)
        {
            if (!trans)
                return null;

            if (trans.name == name)
                return trans;

            for (int i = 0; i < trans.childCount; i++)
            {
                Transform child = trans.GetChild(i);
                Transform found = FindInChildren(child, name);
                if (found)
                {
                    return found;
                }
            }

            return null;
        }

        public static void SetOrderType(GameObject gameObject, string Layer)
        {
            MeshRenderer[] meshArr = gameObject.GetComponentsInChildren<MeshRenderer>(true);
            foreach (MeshRenderer single in meshArr)
            {
                single.sortingLayerName = Layer;
            }
        }

        public static void SaveFile(string fileName, string content)
        {
#if UNITY_EDITOR// && !UNITY_IOS && !UNITY_ANDROID
            string path = Application.dataPath + "/" + fileName;
            System.IO.File.WriteAllText(path, content);
            UnityEngine.Debug.Log("SaveFile " + path);
#endif
        }

        public static string NumberPercent(float sourceNumber, int keepDecimal = 2)
        {
            return (sourceNumber * 100).ToString("f" + keepDecimal) + "%";
        }
        /// <summary>
        /// 格式化数字
        /// </summary>
        /// <param name="sourceNumber">原数字</param>
        /// <param name="isThousand">是否为千位制</param>
        /// <param name="keepDecimal">小数点后保留几位</param>
        /// <param name="isIgnore0">是否忽略最末尾的0</param>
        /// <returns></returns>
        public static string NumberFormat(long sourceNumber, bool isThousand = true, int keepDecimal = 2, bool isIgnore0 = true)
        {
            string _result = "";
            int _span;      //千位/万位
            string[] _units = new string[5];
            if (isThousand)
            {
                _span = 3;
                _units[0] = "";
                _units[1] = "K";
                _units[2] = "M";
                _units[3] = "G";
                _units[4] = "T";
            }
            else
            {
                _span = 4;
                _units[0] = "";
                _units[1] = "万";
                _units[2] = "亿";
                _units[3] = "万亿";
                _units[4] = "亿亿";
            }

            int _scale = (sourceNumber.ToString().Length - 1) / _span;
            string _unit = _units[_scale];
            float _targetNumber = sourceNumber / Mathf.Pow(10, _scale * _span);
            if (isIgnore0)
            {
                if (Mathf.Abs(_targetNumber - (int)_targetNumber) < DOUBLE_DELTA)
                {
                    _result = _targetNumber.ToString();
                }
                else
                {
                    _result = _targetNumber.ToString("f" + keepDecimal);
                    for (int i = _result.Length - 1; i > 0; i--)
                    {
                        if (_result.LastIndexOf("0") == i)
                            _result = _result.Remove(i);
                        else
                            break;
                    }
                }
            }
            else
            {
                _result = _targetNumber.ToString("f" + keepDecimal);
            }
            _result += _unit;
            return _result;
        }

        public static GameObject CreateAfterimage(string resName, GameObject originalSpineGo)
        {
            return AfterimageSequence.CreateAfterimage(resName, originalSpineGo);
        }

        public static void ClearAfterimage(string resName = null)
        {
            AfterimageSequence.ClearAfterimage(resName);
        }

        public static void ShowAfterimageSequence(string resName, GameObject originalSpineGo, Vector3 startPos, Vector3 endPos, Color outlineColor, int count, float delayEndTime, float delayIncTime, string animaitonName, int frameNum)
        {
            AfterimageSequence.ShowAfterimageSequence(resName, originalSpineGo, startPos, endPos, outlineColor, count, delayEndTime, delayIncTime, animaitonName, frameNum);
        }
        public static GameObject ShowAfterimageOneByOne(string resName, GameObject originalSpineGo, Color outlineColor, float delayEndTime, string animaitonName, int frameNum)
        {
            return AfterimageSequence.ShowAfterimageOneByOne(resName, originalSpineGo, outlineColor, delayEndTime, animaitonName, frameNum);
        }
        public static void GetMousePosition(out float x, out float y, out float z)
        {
            var p = Input.mousePosition;
            x = p.x;
            y = p.y;
            z = p.z;
        }

        public static void FGUIScreenToLocal(FairyGUI.GObject go, float sx, float sy, out float outX, out float outY)
        {
            sy = Screen.height - sy;
            Vector2 local = go.GlobalToLocal(new Vector2(sx, sy));
            outX = local.x;
            outY = local.y;
        }
        public static void FGUILocalToScreen(FairyGUI.GObject go, float lx, float ly, out float outX, out float outY)
        {
            Vector2 local = go.LocalToGlobal(new Vector2(lx, ly));
            outX = local.x;
            outY = Screen.height - local.y;
        }
        public static void InverseTransformPoint(Transform transform, float wx, float wy, float wz, out float x, out float y, out float z)
        {
            var pos = transform.InverseTransformPoint(wx, wy, wz);
            x = pos.x;
            y = pos.y;
            z = pos.z;
        }
        public static void ScreenToWorldPoint(Camera cam, float sx, float sy, float sz, out float x, out float y, out float z)
        {
            var pos = cam.ScreenToWorldPoint(new Vector3(sx, sy, sz));
            x = pos.x;
            y = pos.y;
            z = pos.z;
        }
        public static void WorldToScreenPoint(Camera cam, float wx, float wy, float wz, out float x, out float y, out float z)
        {
            var pos = cam.WorldToScreenPoint(new Vector3(wx, wy, wz));
            x = pos.x;
            y = pos.y;
            z = pos.z;
        }
        public static void TransformPoint(Transform transform, float lx, float ly, float lz, out float x, out float y, out float z)
        {
            var pos = transform.TransformPoint(lx, ly, lz);
            x = pos.x;
            y = pos.y;
            z = pos.z;
        }
        public static void TransformPoint(FairyGUI.GObject go, Vector2 pt, FairyGUI.GObject targetSpace, out float x, out float y)
        {
            x = 0;
            y = 0;
            if (go == null) return;
            var v = go.TransformPoint(pt, targetSpace);
            x = v.x;
            y = v.y;

        }
        // 资源加载打印流程 打印层级0 不打印
        public static int UIPackageResLog = 0;

        public static void UnloadUnusedAssets(int clearType)
        {
            switch (clearType)
            {
                case 0:
                    //不清
                    break;
                case 1:
                    ResourceManager.ClearAllCache();
                    break;
                case 2:
                    ResourceManager.ClearPrefabCache();
                    break;
                case 3:
                    ResourceManager.ClearEffectCache();
                    break;
            }
            Resources.UnloadUnusedAssets();
        }

        public static void UnloadSingleLihui(string name)
        {
            ResourceManager.ClearSingleLihui(name);
        }

        public static void UnloadLihui()
        {
            ResourceManager.ClearLihui();
        }

        public static void UnloadBattleRes()
        {
            ResourceManager.ClearResOnBattleEnd();
        }

        public static void UnloadLihuiCache(int num)
        {
            ResourceManager.ClearLihuiCache(num);
        }

        public static void UnloadRoleCache(string[] res, int num)
        {
            ResourceManager.ClearRoleCache(res, num);
        }

        public static void UnloadLihuiCache(string[] res)
        {
            ResourceManager.ClearLihuiCache(res);
        }

        //解析Json -> 字典
        public static Dictionary<string, object> JsonToDictionary(string jsonStr)
        {
            Dictionary<string, object> _resultDic = new Dictionary<string, object>();
            if (string.IsNullOrEmpty(jsonStr))
                return _resultDic;
            JsonData _jsonData = JsonMapper.ToObject(jsonStr);
            IDictionary _jsonDic = _jsonData as IDictionary;
            foreach (string key in _jsonDic.Keys)
            {
                object _value = _jsonDic[key];
                _resultDic.Add(key, _value.ToString());
            }
            return _resultDic;
        }

        public static int GetLuaObjectCount()
        {
            int ret = 0;
            if (LuaManager._translator != null)
            {
                ret = LuaManager._translator.GetObjCnt();
            }
            return ret;
        }

        public static string GetIP()
        {
            NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface adater in adapters)
            {
                if (adater.Supports(NetworkInterfaceComponent.IPv4))
                {
                    UnicastIPAddressInformationCollection UniCast = adater.GetIPProperties().UnicastAddresses;
                    if (UniCast.Count > 0)
                    {
                        foreach (UnicastIPAddressInformation uni in UniCast)
                        {
                            if (uni.Address.AddressFamily == AddressFamily.InterNetwork)
                            {
                                Debug.Log(uni.Address.ToString());
                                return uni.Address.ToString();
                            }
                        }
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 找到spine动画下指定的材质球
        /// </summary>
        public static Material GetMaterialOnSkeletonAnimation(SkeletonAnimation anim, string name)
        {
            foreach (AtlasAssetBase item in anim.skeletonDataAsset.atlasAssets)
            {
                foreach (Material mat in item.Materials)
                {
                    if (mat.name == name)
                    {
                        return mat;
                    }
                }
            }

            return null;
        }

        public static Material[] SetSkeletonAnimMatrialStencil(FairyGUI.GObject obj, int stencil)
        {
            List<Material> ls = new List<Material>();
            var arr = obj.displayObject.gameObject.GetComponentsInChildren<SkeletonAnimation>(true);
            for (int i = 0; i < arr.Length; i++)
            {

                foreach (AtlasAssetBase item in arr[i].skeletonDataAsset.atlasAssets)
                {
                    foreach (Material mat in item.Materials)
                    {
                        mat.SetFloat("_StencilComp", stencil);
                        ls.Add(mat);
                    }
                }
            }
            return ls.ToArray();
        }

        public static Vector3 Parabola(Vector3 start, Vector3 end, float height, float t)
        {
            float Func(float x) => 4 * (-height * x * x + height * x);

            var mid = Vector3.Lerp(start, end, t);

            return new Vector3(mid.x, Func(t) + Mathf.Lerp(start.y, end.y, t), mid.z);
        }


        public static Vector2 Parabola(Vector2 start, Vector2 end, float height, float t)
        {
            float Func(float x) => 4 * (-height * x * x + height * x);

            var mid = Vector2.Lerp(start, end, t);

            return new Vector2(mid.x, Func(t) + Mathf.Lerp(start.y, end.y, t));
        }

        public static void FlyParabola2D(GameObject target, Vector2 start, Vector2 end, float height, float t)
        {
            DOTween.To(setter: value =>
            {
                target.transform.position = Parabola(start, end, height, value);
            }, startValue: 0, endValue: 1, duration: t)
           .SetEase(Ease.Linear);

        }

        public static void FlyParabola3D(GameObject target, Vector3 start, Vector3 end, float height, float t)
        {
            DOTween.To(setter: value =>
            {
                target.transform.position = Parabola(start, end, height, value);
            }, startValue: 0, endValue: 1, duration: t)
           .SetEase(Ease.Linear);

        }
        public static string GetLanguageFromLua(string key)
        {
            string str = "";
            var obj = LuaHelper.GetLuaManager().CallFunc("GetLanguageByKey", new object[] { key });
            if (obj != null)
            {
                for (int i = 0; i < obj.Length; i++)
                {
                    if (obj[i] is string)
                    {
                        str += obj[i];
                    }
                }
            }
            return str;
        }

        //定义方法生成二维码
        private static Color32[] Encode(string textForEncoding, int width, int height)
        {
            var writer = new BarcodeWriter
            {
                Format = BarcodeFormat.QR_CODE,
                Options = new QrCodeEncodingOptions
                {
                    Height = height,
                    Width = width
                }
            };
            return writer.Write(textForEncoding);
        }

        //根据文本生成二维码
        public static Texture2D CreateQRCode(string url)
        {
            if (string.IsNullOrEmpty(url))
                return null;
            Texture2D encoded = new Texture2D(256, 256);


            //二维码写入图片
            var color32 = Encode(url, encoded.width, encoded.height);
            encoded.SetPixels32(color32);

            //Texture2D logo = Resources.Load<Texture2D>("applogo");
            //logo.format = TextureFormat.RGBA32;
            
            //encoded.SetPixels32(logo.GetPixels32());
            //encoded.Apply();


            ////重新赋值一张图，计算大小,避免白色边框过大
            Texture2D encoded1;
            encoded1 = new Texture2D(190, 190, TextureFormat.RGBA32, false);//创建目标图片大小
            //encoded.SetPixels(92, 92, 32, 32, logo.GetPixels());

            var array = encoded.GetPixels(32, 32, 190, 190);
            encoded1.SetPixels(array);

            //var logoarray = logo.GetPixels();

            //int delta = encoded1.width / 2 - logo.width / 2;
            //for (int i = 0; i < logo.width; i++)
            //{
            //    for (int j = 0; j < logo.height; j++)
            //    {
            //        Color rgb = logo.GetPixel(i, j);

            //        if (rgb.a != 0)
            //        {
            //            encoded1.SetPixel(i + delta, j + delta, rgb);
            //        }
            //    }
            //}

            encoded1.Apply();
            return encoded1;
        }

        /// <summary>
        /// 获取安卓包名
        /// </summary>
        public static string GetApkPackageName()
        {

            string _strPackageName = "";
#if (UNITY_ANDROID && !UNITY_EDITOR)
            using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            {
                using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
                {
                    using (AndroidJavaObject javaObj = currentActivity.Call<AndroidJavaObject>("getPackageName"))
                    {
                        _strPackageName = javaObj.Call<string>("toString");
                    }
                }
            }
#endif
            return _strPackageName;
        }
    }
}